// 回调函数
// 页面的根函数

import * as Blockly from 'blockly/core'

// 1---------------回调函数 - 回调函数--------------------------
const json = {
  type: 'callback_function_expression',
  'message0': '回调函数 %1 %2',
  args0: [
    {
      'type': 'input_dummy',
      'name': 'PARAM_INPUT'
    },
    {
      'type': 'input_statement',
      'name': 'FUNCBODY'
    }
  ],
  style: 'procedure_blocks',
  'output': 'callback_function_expression',
  // 'style': 'text_blocks',
  'helpUrl': '',
  'tooltip': '',
  // nextStatement: true,
  inputsInline: true,
  'mutator': 'param_mutator'
}

// 创建积木
Blockly.Blocks['callback_function_expression'] = {
  init: function () {
    this.jsonInit(json)
  }
}

const mixinObj = {
  /**
   * Create XML to represent number of text inputs.
   * @return {!Element} XML storage element.
   * @this {Blockly.Block}
   */
  mutationToDom: function () {
    var container = Blockly.utils.xml.createElement('mutation')
    container.setAttribute('items', this.itemCount_)
    return container
  },
  /**
   * Parse XML to restore the text inputs.
   * @param {!Element} xmlElement XML storage element.
   * @this {Blockly.Block}
   */
  domToMutation: function (xmlElement) {
    this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10) || 0
    this.updateShape_()
  },
  /**
   * Populate the mutator's dialog with this block's components.
   * @param {!Blockly.Workspace} workspace Mutator's workspace.
   * @return {!Blockly.Block} Root block in mutator.
   * @this {Blockly.Block}
   */
  // decompose: function (workspace) {
  //   var containerBlock = workspace.newBlock('param_create_join_container')
  //   containerBlock.initSvg()
  //   var connection = containerBlock.getInput('STACK').connection
  //   for (var i = 0; i < this.itemCount_; i++) {
  //     var itemBlock = workspace.newBlock('param_create_join_item')
  //     itemBlock.initSvg()
  //     connection.connect(itemBlock.previousConnection)
  //     connection = itemBlock.nextConnection
  //   }
  //   return containerBlock
  // },
  /**
   * Reconfigure this block based on the mutator dialog's components.
   * @param {!Blockly.Block} containerBlock Root block in mutator.
   * @this {Blockly.Block}
   */
  // compose: function (containerBlock) {
  //   var itemBlock = containerBlock.getInputTargetBlock('STACK')
  //   // Count number of inputs.
  //   var connections = []
  //   while (itemBlock) {
  //     connections.push(itemBlock.valueConnection_)
  //     itemBlock = itemBlock.nextConnection &&
  //       itemBlock.nextConnection.targetBlock()
  //   }
  //   // Disconnect any children that don't belong.
  //   for (let i = 0; i < this.itemCount_; i++) {
  //     var connection = this.getInput('ADD' + i).connection.targetConnection
  //     if (connection && connections.indexOf(connection) == -1) {
  //       connection.disconnect()
  //     }
  //   }
  //   this.itemCount_ = connections.length
  //   this.updateShape_()
  //   // Reconnect any child blocks.
  //   for (let i = 0; i < this.itemCount_; i++) {
  //     Blockly.Mutator.reconnect(connections[i], this, 'ADD' + i)
  //   }
  //   // var stackConnection = this.getInput('FUNCBODY').connection
  //   // this.statementConnection_ = stackConnection.targetConnection
  //   // Blockly.Mutator.reconnect(this.statementConnection_, this, 'FUNCBODY')
  //   // this.statementConnection_ = null
  //   // const funcStatementConnection = this.getInput('FUNCBODY').connection.targetConnection
  //   // Blockly.Mutator.reconnect(funcStatementConnection, this, 'FUNCBODY')
  // },
  /**
   * Store pointers to any connected child blocks.
   * @param {!Blockly.Block} containerBlock Root block in mutator.
   * @this {Blockly.Block}
   */
  // saveConnections: function (containerBlock) {
  //   var itemBlock = containerBlock.getInputTargetBlock('STACK')
  //   var i = 0
  //   while (itemBlock) {
  //     var input = this.getInput('ADD' + i)
  //     itemBlock.valueConnection_ = input && input.connection.targetConnection
  //     i++
  //     itemBlock = itemBlock.nextConnection &&
  //       itemBlock.nextConnection.targetBlock()
  //   }
  //   const funcBody = this.getInput('FUNCBODY')
  //   containerBlock.statementConnection_ = funcBody && funcBody.connection.targetBlock()
  // },
  /**
   * Modify this block to have the correct number of inputs.
   * @private
   * @this {Blockly.Block}
   */
  updateShape_: function () {
    // Add new inputs.
    for (var i = 0; i < this.itemCount_; i++) {
      if (!this.getInput('ADD' + i)) {
        var input = this.appendValueInput('ADD' + i)
        if (i === 0) {
          input.appendField('参数')
        }
      }
    }
    // this.appendStatementInput('FUNCBODY')
    // Remove deleted inputs.
    while (this.getInput('ADD' + i)) {
      this.removeInput('ADD' + i)
      i++
    }

    const stackConnection = this.getInput('FUNCBODY').connection
    const statementConnection_ = stackConnection.targetConnection
    this.removeInput('FUNCBODY')
    this.appendStatementInput('FUNCBODY')
    Blockly.Mutator.reconnect(statementConnection_, this, 'FUNCBODY')

    // var stackConnection = this.getInput('FUNCBODY').connection
    // this.statementConnection_ = stackConnection.targetConnection
    // var stackBlock = stackConnection.targetBlock()
    // this.removeInput('FUNCBODY')
  }
  // reconnectChildBlocks_: function (valueConnections, statementConnections,
  //   elseStatementConnection) {
  // for (var i = 1; i <= this.elseifCount_; i++) {
  //   Blockly.Mutator.reconnect(valueConnections[i], this, 'IF' + i)
  //   Blockly.Mutator.reconnect(statementConnections[i], this, 'DO' + i)
  // }
  // Blockly.Mutator.reconnect(elseStatementConnection, this, 'ELSE')
  // }
}

const helpFun = function () {
  // 初始化的参数个数
  this.itemCount_ = 0
  this.updateShape_()
  // this.setMutator(new Blockly.Mutator(['param_create_join_item']))
}
Blockly.Extensions.registerMutator('param_mutator', mixinObj, helpFun)

Blockly.JavaScript['callback_function_expression'] = function (block) {
  var elements = new Array(block.itemCount_)
  for (var i = 0; i < block.itemCount_; i++) {
    elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i,
      Blockly.JavaScript.ORDER_COMMA)
  }
  var params = elements.join(',')
  var body = Blockly.JavaScript.statementToCode(block, 'FUNCBODY')
  const code = `async (${params}) => {\n${body}}`
  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]
}

// 2---------------------页面的根函数----------------------
const rootHelpFun = function () {
  // Initialize the mutator values.
  this.itemCount_ = 1
  this.composeKey = 'eventKey'
  this.setDeletable(false)
  this.updateShape_()
  // this.setMutator(new Blockly.Mutator(['param_create_join_item']))
}
Blockly.Extensions.registerMutator('root_mutator', mixinObj, rootHelpFun)
const exportJson = {
  type: 'root_function_expression',
  'message0': '%1 %2 %3',
  args0: [
    {
      'type': 'field_label_serializable',
      'name': 'ROOT_NAME_INPUT',
      'text': '函数名'
    },
    // {
    //   'type': 'input_value',
    //   'name': 'NAME_INPUT',
    //   'text': 'root'
    // },
    {
      'type': 'input_dummy',
      'name': 'PARAM_INPUT'
    },
    {
      'type': 'input_statement',
      'name': 'FUNCBODY'
    }
  ],
  colour: '#00627A',
  // style: 'action_blocks',
  'enableContextMenu': false,
  'helpUrl': '',
  'tooltip': 'context上下文，在事件方法中会在第一个参数中内置该对象',
  // nextStatement: true,
  inputsInline: true,
  'mutator': 'root_mutator'
}

// 创建积木
Blockly.Blocks['root_function_expression'] = {
  init: function () {
    this.jsonInit(exportJson)
  }
}

Blockly.JavaScript['root_function_expression'] = function (block) {
  var elements = new Array(block.itemCount_)
  // var name = Blockly.JavaScript.valueToCode(block, 'NAME_INPUT', Blockly.JavaScript.ORDER_COMMA)
  // var name = block.getFieldValue('ROOT_NAME_INPUT')
  const name = block.composeKey
  for (var i = 0; i < block.itemCount_; i++) {
    elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i,
      Blockly.JavaScript.ORDER_COMMA) || '\'\''
  }
  var params = elements.join(',')
  var body = Blockly.JavaScript.statementToCode(block, 'FUNCBODY')
  const code = `export function ${name}(${params}){\n${body}}`
  return code
}

// ------------------返回-----------------------

Blockly.Blocks['return_block'] = {
  init: function () {
    // this.setColour(290)
    this.setStyle('procedure_blocks')
    this.appendValueInput('RETURN')
      .appendField('返回')
    this.setPreviousStatement(true, null)
    this.setNextStatement(true, null)
    this.setInputsInline(false)
  }
}

Blockly.JavaScript['return_block'] = function (block) {
  var value = Blockly.JavaScript.valueToCode(
    block,
    'RETURN',
    Blockly.JavaScript.ORDER_ATOMIC
  )
  return `return ${value}\n`
}
